package cn.qingyun.gis.modules.init.utils;

import cn.hutool.core.annotation.Alias;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.qingyun.gis.modules.express.util.anno.CSVField;
import com.csvreader.CsvReader;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.Scanner;

@Slf4j
public class CsvTool {
    private CsvTool() {
        throw new IllegalStateException("Utility class");
    }

    @SneakyThrows
    public static <T, R> List<R> transferFile(MultipartFile file, Class<T> fClass, Class<R> tClass) {
        CsvReader csvReader = new CsvReader(file.getInputStream(), StandardCharsets.UTF_8);
        // 读表头
        csvReader.setSafetySwitch(false);
        csvReader.readHeaders();

        List<T> imports = Lists.newArrayList();
        // 读内容
        while (csvReader.readRecord()) {
            imports.add(CsvTool.toBean(csvReader, fClass));
        }

        List<R> records = Lists.newArrayList();
        if (CollUtil.isNotEmpty(imports)) {
            for (T anImport : imports) {
                R district = tClass.newInstance();

                BeanUtils.copyProperties(anImport, district);
                records.add(district);
            }
        }

        return records;
    }

    @SneakyThrows
    public static <T> List<T> transferFile(InputStream inputStream, Class<T> fClass) {
        //预处理， 替换双引号
        String content = IoUtil.readUtf8(inputStream);
        content = content.replaceAll("\uFEFF", "");

        CsvReader csvReader = new CsvReader(IoUtil.toUtf8Stream(content), Charsets.UTF_8);
        // 读表头
        csvReader.setSafetySwitch(false);
        csvReader.readHeaders();

        List<T> imports = Lists.newArrayList();
        // 读内容
        while (csvReader.readRecord()) {
            imports.add(CsvTool.toBean(csvReader, fClass));
        }

        return imports;
    }

    @SneakyThrows
    public static <T> List<T> transferFile(File file, Class<T> fClass) {
        //预处理， 替换双引号
        String content = IoUtil.readUtf8(FileUtil.getInputStream(file));
        content = content.replaceAll("\uFEFF", "");

        CsvReader csvReader = new CsvReader(IoUtil.toUtf8Stream(content), Charsets.UTF_8);
        // 读表头
        csvReader.setSafetySwitch(false);
        csvReader.readHeaders();

        List<T> imports = Lists.newArrayList();
        // 读内容
        while (csvReader.readRecord()) {
            imports.add(CsvTool.toBean(csvReader, fClass));
        }

        return imports;
    }

    @SneakyThrows
    public static <T> T toBean(CsvReader csvReader, Class<T> tClass) {
        JSONObject jsonObject = new JSONObject();
        for (Field field : tClass.getDeclaredFields()) {
            CSVField annotation = field.getAnnotation(CSVField.class);
            if (Objects.nonNull(annotation)) {
                String key = annotation.value();
                jsonObject.set(field.getName(), csvReader.get(key));
            }
        }

        return jsonObject.toBean(tClass);
    }

    /**
     * 对原csv文件进行表头追加
     */
    @SneakyThrows
    public static void addHead(File file, String header) {
        try (RandomAccessFile raf = new RandomAccessFile(file, "rw");
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = raf.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }

            raf.seek(0);
            raf.write((header + System.lineSeparator()).getBytes(StandardCharsets.UTF_8));
            raf.write(baos.toByteArray());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @SneakyThrows
    public static void transferTab(File file) {
        String originalDelimiter = "\t";
        String convertedDelimiter = ",";
        String quote = "\"";
        try {
            // 创建输入文件的Scanner对象
            Scanner scanner = new Scanner(file);

            // 创建StringBuilder对象来存储转换后的数据
            StringBuilder convertedData = new StringBuilder();

            // 逐行读取CSV文件
            while (scanner.hasNextLine()) {
                String line = scanner.nextLine();

                // 使用split()方法将每行数据按照分隔符拆分成单列元素
                String[] columns = line.split(originalDelimiter);

                // 遍历每个单列元素，并在其前后添加引号
                for (String column : columns) {
                    convertedData.append(quote).append(column).append(quote).append(convertedDelimiter);
                }

                // 删除最后一个多余的分隔符
                convertedData.deleteCharAt(convertedData.length() - 1);
                convertedData.append("\n");
            }

            // 关闭原文件
            scanner.close();

            // 使用FileWriter类将StringBuilder对象中的数据写入原文件
            FileWriter writer = new FileWriter(file);
            writer.write(convertedData.toString());

            // 关闭FileWriter
            writer.close();
            log.debug("csv文件分隔符转换完成");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据传入的数据 和路径生成CSV文件
     *
     * @param filePath 文件路径 带文件名
     * @param dataList 文件数据
     */
    public static void generateCsv(String filePath, List<T> dataList) {
        log.debug("CSV文件生成成功，路径：{}", filePath);
        if (CollUtil.isEmpty(dataList)) {
            log.debug("generateCsv end dataList empty");
            return;
        }
        long start = System.currentTimeMillis();
        // 获取映射类的字段信息
        Class<?> clazz = dataList.get(0).getClass();
        Field[] fields = ReflectUtil.getFields(clazz);

        // 创建CSV写入器
        CsvWriter writer = CsvUtil.getWriter(filePath, CharsetUtil.CHARSET_UTF_8);

        // 写入表头
        String[] headers = new String[fields.length];
        for (int i = 0; i < fields.length; i++) {
            Alias alias = fields[i].getAnnotation(Alias.class);
            if (ObjectUtil.isNotNull(alias)) {
                headers[i] = alias.value();
            } else {
                headers[i] = fields[i].getName();
            }
        }
        writer.write(headers);

        // 写入数据
        for (T data : dataList) {
            String[] row = new String[fields.length];
            for (int i = 0; i < fields.length; i++) {
                Object value = ReflectUtil.getFieldValue(data, fields[i]);
                row[i] = ObjectUtil.isNull(value) ? StrUtil.EMPTY : value.toString();
            }
            writer.write(row);
        }

        // 关闭写入器
        writer.close();
        log.debug("---CSV文件生成完成,耗时:" + (System.currentTimeMillis() - start) + "毫秒----");
    }

}

















